﻿//----------------------------------------------------------------
// Desc: 图形设备对象
// Edit: ShowLong, http://blog.csdn.net/showlong
//
// Date Created: 2010-06-11
//
// Update Date : 
//
// Copyright (c) Fuel4D (http://www.fuel4d.com), All rights reserved.
//
//----------------------------------------------------------------
#pragma once


#include "Engine/FEngineDefine.h"


//----------------------------------------------------------------
//
//----------------------------------------------------------------
#pragma pack(push, 1)
struct FBUF_3D_TERRAIN 
{
    BYTE frame_mode;
    float ex, ey;
    FIDTEXTURE height_tex, alpha_tex;
    FTERRAIN_BLEND_TEXTURE blend[eCD_CHUNK_ALPHA_LAYER];
};
typedef FVector< FBUF_3D_TERRAIN > FV_BUF_3D_TERRAIN;
struct FBUF_3D_VEGETATION
{
    FIDTEXTURE noise, id;
    size_t count;
    FVEGETATION_PROP* lst;
};
typedef FVector< FBUF_3D_VEGETATION > FV_BUF_3D_VEGETATION;
struct FBUF_3D_WATER
{
    float ex, ey, height;
    FCOLOR color;
};
typedef FVector< FBUF_3D_WATER > FV_BUF_3D_WATER;
class FAnimation;
struct FBUF_3D_SUBSET
{
    FIDMODEL mod_id;
    FAnimation* anim;
    size_t sub_idx;
    float alpha;
};
typedef FVector< FBUF_3D_SUBSET > FV_BUF_3D_SUBSET;
#pragma pack(pop)


//----------------------------------------------------------------
//
//----------------------------------------------------------------
class IFGraph : public IFService
{
protected:
    explicit IFGraph(EF_DEVICE_TYPE type, IFEngine* p)
        :IFService(p)
        ,nType(type)
    {}

public:
    // 当前图形渲染器类型
    const EF_DEVICE_TYPE nType;

    // 清缓冲区表面
    // .rc 清屏区域
    // .flags 清屏标记
    // .color 填充颜色
    virtual bool Clear(FRect* rc, EF_CLEAR_FLAGS flags, DWORD color) = 0;
    // 清缓冲区表面
    // .rc 清屏区域，rc为0则清整个表面
    // .flags 清屏标记
    // .color 填充颜色
    // .z 填充Z值
    // .stencil 填充模板值
    virtual bool Clear(FRect* rc, EF_CLEAR_FLAGS flags, DWORD color, float z, DWORD stencil) = 0;
    // 取得后备缓冲区尺寸
    virtual float GetBackW() = 0;
    virtual float GetBackH() = 0;
    // 将后背缓冲区复制到贴图上去
    // .tex 必须为[RT]或者[RT Texture]
    virtual bool GetBackbuffer(FIDTEXTURE tex) = 0;
    // 修改后背缓冲区为目标贴图，并压栈当前后背缓冲区，以方便还原后背缓冲区
    // .tex 切换到的目标贴图
    virtual bool PushBackbuffer(FIDTEXTURE tex) = 0;
    // 还原后背缓冲区
    virtual void PopBackbuffer() = 0;
    // 屏幕截图（在Commit操作之后才能截图，否则那些还在缓冲区没有渲染的元素无法截取到）
    // .filename 截图存到目标文件
    // .format 截图格式(D3DXIMAGE_FILEFORMAT之一)
    virtual bool SnapshotToFile(const WCHAR* filename, DWORD format) = 0;
    virtual bool SnapshotToFile(const ACHAR* filename, DWORD format) = 0;
    // 屏幕截图到BGRA缓冲区（在Commit操作之后才能截图，否则那些还在缓冲区没有渲染的元素无法截取到）
    // .width, height 返回图片尺寸
    // .bgra 返回BGRA缓存
    virtual bool SnapshotToBuffer(size_t& width, size_t& height, FV_BYTE& bgra) = 0;
    // 设置脏矩形(窗口句柄级截剪)
    // .pdata 脏矩形数据地址(为null时表示清除脏矩形)
#if FUEL_OS_WINDOWS
    virtual void SetRegionData(const RGNDATA* pdata) = 0;
#endif
    // 设置各转换矩阵
    virtual void SetTransform(EF_TRANSFORM_TYPE type, FMATRIX* mat) = 0;

//----------------------------------------------------------------
// 以下是运行接口，由实现者提供，用户不能调用，以下函数都是立即模式，不做容错处理
//----------------------------------------------------------------
    // 开始绘制
    virtual bool BeginRender() = 0;
    // 结束绘制
    virtual bool EndRender() = 0;
    // 翻转图形设备
    virtual bool Present() = 0;
    // 测试设备是否可用
    // .return false 表示设备丢失
    virtual bool TestCooperativeLevel() = 0;
    // 设备丢失（不用实现IFService::Lost）
    virtual void DeviceLost() = 0;
    // 设备恢复（不用实现IFService::Reset）
    virtual bool DeviceReset(bool init_reset) = 0;
    // 清理设置的VS\PS状态（用于固定管线与非固定管线切换时调用）
    virtual void ClearShader() = 0;
    // 设置裁剪区
    virtual void SetScissorRect(const FRect* prect) = 0;
    // 原始渲染方法
    virtual void DrawBuffer(bool is3d, EF_FVF fvf, DWORD flags, FIDTEXTURE tex1, FIDTEXTURE tex2, EF_PRIMITIVE_TYPE primitive_type, UINT primitive_count,
        const void* pvertex, UINT vertex_count, const void* pindex, UINT stride) = 0;
    // 原始渲染方法
    virtual void DrawBuffer(bool is3d, EF_FVF fvf, DWORD flags, EF_PRIMITIVE_TYPE primitive_type, UINT primitive_count, 
        const void* pvertex, UINT vertex_count, UINT stride) = 0;
    // 获取pass
    virtual IFPass* GetPass(DWORD type) = 0;
    // 渲染2D精灵
    virtual void Draw_2D_Sprite(EF_FVF fvf, DWORD flags, FIDTEXTURE tex, EF_PRIMITIVE_TYPE primitive_type, UINT primitive_count, UINT primitive_points,
        const void* pvertex, UINT vertex_count, const void* pindex, UINT stride) = 0;
    // 渲染天空盒
    virtual void Draw_3D_Skybox(FIDTEXTURE sky_tex) = 0;
    // 渲染单个地块
    virtual void Draw_3D_Terrain(FBUF_3D_TERRAIN& ck) = 0;
    // 渲染植被
    virtual void Draw_3D_Vegetation(FBUF_3D_VEGETATION& vc) = 0;
    // 渲染水面
    virtual void Draw_3D_Water(FBUF_3D_WATER& wk) = 0;
    // 渲染子集
    virtual void Draw_3D_Subset(FBUF_3D_SUBSET& sn) = 0;

    // 测试贴图文件是否正常，D3D时内部调用D3DXGetImageInfoFromFile
    virtual bool __GetTextureInfo(const WCHAR* filename) = 0;
    virtual bool __GetTextureInfo(const ACHAR* filename) = 0;
    // 创建文件贴图
    virtual bool __CreateTexture(FIDTEXTURE id, FTEXTURE_PTR& tex, const WCHAR* file, IFTextureInfo& info, bool cube) = 0;
    virtual bool __CreateTexture(FIDTEXTURE id, FTEXTURE_PTR& tex, const ACHAR* file, IFTextureInfo& info, bool cube) = 0;
    // 创建内存贴图
    virtual bool __CreateTexture(FIDTEXTURE id, FTEXTURE_PTR& tex, UINT width, UINT height, UINT MipLevels,
        EF_TEXTURE_TYPE tt, EF_FORMAT format, EF_POOL Pool) = 0;
    // 创建文件缓存贴图
    virtual bool __CreateTexture(FIDTEXTURE id, FTEXTURE_PTR& tex, const BYTE* buf, size_t size,
        UINT& width, UINT& height, UINT& src_width, UINT& src_height, UINT& mip_level, EF_TEXTURE_TYPE& tt, EF_FORMAT& format, EF_POOL& pool) = 0;
    // 创建VERTEX
    virtual bool __CreateVertexBuffer(void* data, size_t Length, EF_TEXTURE_TYPE Usage, EF_FVF FVF, EF_POOL Pool, FVERTEX_PTR& pv) = 0;
    // 释放VERTEX
    virtual void __DestoryVertexBuffer(FVERTEX_PTR& p) = 0;
    // 创建VERTEXDECL
    virtual bool __CreateVertexDeclaration(FVVERTEXELEMENT& ve, FVERTEXDECL_PTR& vp) = 0;
    // 释放VERTEXDECL
    virtual void __DestoryVertexDeclBuffer(FVERTEXDECL_PTR& p) = 0;
    // 创建INDEX(IDX16)
    virtual bool __CreateIndexBuffer(void* data, size_t Length, EF_TEXTURE_TYPE Usage, EF_POOL Pool, FINDEX_PTR& pi) = 0;
    // 释放INDEX
    virtual void __DestoryIndexBuffer(FINDEX_PTR& p) = 0;
    // 释放引擎之前调用
    virtual void __PreRelease() = 0;
    // 创建顶点描述
    virtual void __MakeDecl(EF_STREAM_TYPE t, FVERTEXELEMENT& vl, size_t* offset = 0) = 0;
    // 创建贴图数据
    virtual FTextureFile* __NewTextureData(IFEngine* p, FIDHASH hash, FTEXTURE_PTR default_tex) = 0;
    // 删除贴图数据
    virtual void __DelTextureData(FTextureFile*& td) = 0;


    // 屏蔽以下函数
private:
    virtual void Lost(){ FASSERT_STR(_T("不允许调用此接口，请改用DeviceLost")); }
    virtual void Reset(){ FASSERT_STR(_T("不允许调用此接口，请改用DeviceReset")); }
};